package com.wsoft.config;

import cn.hutool.core.util.ObjUtil;
import com.wsoft.constant.CommonConstant;
import com.wsoft.core.context.AuthLoginModeContextHolder;
import com.wsoft.entity.TsJobEntity;
import com.wsoft.entity.TsJobLogEntity;
import com.wsoft.system.manager.TsJobLogManager;
import com.wsoft.system.manager.TsJobManager;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;

/**
 * @Author z001
 * @Date 2024/12/25 08:05
 */
@Component
public class CustomJobListener implements JobListener {

    private static final ThreadLocal<TsJobLogEntity> JOB_LOG_THREAD_LOCAL = new ThreadLocal<>();

    @Autowired
    private TsJobManager jobManager;
    @Autowired
    private TsJobLogManager jobLogManager;


    @Override
    public String getName() {
        return this.getClass().getName();
    }

    @Override
    public void jobToBeExecuted(JobExecutionContext context) {
        String code = context.getJobDetail().getKey().getName();
        TsJobEntity jobEntity = jobManager.getByCode(code);

        LocalDateTime now = LocalDateTime.now();
        context.getJobDetail().getJobDataMap().put(CommonConstant.NOW_EXECUTE_TIME, now);
        if(ObjUtil.isNotNull(jobEntity.getLastExecuteTime())){
            context.getJobDetail().getJobDataMap().put(CommonConstant.LAST_EXECUTE_TIME, jobEntity.getLastExecuteTime());
        }

        //更新最后一次执行时间 ==> 为当前时间
        AuthLoginModeContextHolder.need();
        jobEntity.setLastExecuteTime(now);
        jobManager.updateById(jobEntity);

        TsJobLogEntity jobLog = new TsJobLogEntity();
        jobLog.setStartTime(getNowTime());
        if (null != jobEntity) {
            jobLog.setCode(jobEntity.getCode());
            jobLog.setName(jobEntity.getName());
            jobLog.setParams(jobEntity.getParams());
            jobLog.setDescription(jobEntity.getDescription());
            jobLog.setCron(jobEntity.getCron());
            jobLog.setClassPath(jobEntity.getClassPath());
            jobLog.setJobId(jobEntity.getId());
        }
        JOB_LOG_THREAD_LOCAL.set(jobLog);
    }

    @Override
    public void jobExecutionVetoed(JobExecutionContext jobExecutionContext) {
        // 如果任务被否决，可以在这里处理
        System.out.println("如果任务被否决，可以在这里处理");
    }

    @Override
    public void jobWasExecuted(JobExecutionContext jobExecutionContext, JobExecutionException e) {
        AuthLoginModeContextHolder.need();
        String code = jobExecutionContext.getJobDetail().getKey().getName();
        TsJobEntity jobEntity = jobManager.getByCode(code);


        TsJobLogEntity jobLog = JOB_LOG_THREAD_LOCAL.get();
        if (jobLog != null) {
            if (e != null) {
                // 任务执行失败，记录详细的错误信息
                LocalDateTime now = getNowTime();
                jobLog.setEndTime(now);
                jobLog.setExecuteTimeMillis(calculateIntervalInMilliseconds(jobLog.getStartTime(), now));
                jobLog.setResult(0);
                jobLog.setException(ExceptionUtils.getStackTrace(e));
                AuthLoginModeContextHolder.need();
                jobLogManager.save(jobLog);
                JOB_LOG_THREAD_LOCAL.remove();
            } else {
                LocalDateTime now = getNowTime();
                jobLog.setEndTime(now);
                jobLog.setExecuteTimeMillis(calculateIntervalInMilliseconds(jobLog.getStartTime(), now));
                jobLog.setResult(1);
                AuthLoginModeContextHolder.need();
                jobLogManager.save(jobLog);
                JOB_LOG_THREAD_LOCAL.remove();
            }
        }
    }


    /**
     * 计算 givenDateTime 和 当前时间的 时间差 单位毫秒
     *
     * @param givenDateTime
     * @return
     */
    private static long calculateIntervalInMilliseconds(LocalDateTime givenDateTime, LocalDateTime now) {

        // 将给定的 LocalDateTime 对象转换为 Instant 对象
        long givenDateTimeMillis = givenDateTime.toInstant(ZoneOffset.UTC).toEpochMilli();

        // 将当前的 LocalDateTime 对象转换为 Instant 对象
        long nowMillis = now.toInstant(ZoneOffset.UTC).toEpochMilli();

        // 计算时间间隔（以毫秒为单位）
        return nowMillis - givenDateTimeMillis;
    }

    /**
     * 获取当前时间的毫秒值
     */
    public static LocalDateTime getNowTime() {
        // 获取当前时间的毫秒值
        long currentTimeMillis = System.currentTimeMillis();
        // 将毫秒值转换为 Instant 对象
        Instant instant = Instant.ofEpochMilli(currentTimeMillis);
        // 将 Instant 对象转换为 LocalDateTime 对象，使用系统默认时区
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }


}
